﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Rappelz.GameServer.Scripting;
using Rappelz.GameServer.Network;

namespace Rappelz.GameServer
{
    public class AllowedCommandInfo
    {

        public class CommandInfo
        {
            public string szCommand = "";           // 0x00
            public string szParameter = "";         // 0x41
        }

        public int nPermisson;                 // 0x00
        public List<CommandInfo> vCommandInfoList = new List<CommandInfo>(); //0x04
    }

    public class SCheatCommand
    {
        public static List<SCheatCommand> v_Commands = new List<SCheatCommand>();

        public static void Init()
        {
            v_Commands.Add(new SCheatCommand("notice", onCheatNotice, true, 0));
            v_Commands.Add(new SCheatCommand("run", onRunScript, true, 0));
            v_Commands.Add(new SCheatCommand("position", onCheatPosition, true, 0));
            v_Commands.Add(new SCheatCommand("plist", Messages.SendPartyInfo, true, 0));
            v_Commands.Add(new SCheatCommand("battle", onBattleMode, true, 0));
            v_Commands.Add(new SCheatCommand("sitdown", onCheatSitdown, true, 0));
            v_Commands.Add(new SCheatCommand("standup", onCheatStandUp, true, 0));
            v_Commands.Add(new SCheatCommand("gcreate", onGuildCreate, true, 2));
            v_Commands.Add(new SCheatCommand("gicon", onRequestGuildIconInfo, true, 2));
            v_Commands.Add(new SCheatCommand("gupdateicon", onGuildIconUpdate, true, 0));
            v_Commands.Add(new SCheatCommand("graidsiegetip", onGuildRaidSeigeTip, true, 0));

            
            
        }

        public static SCheatCommand FindCommand(string cmd)
        {
            string[] acmd = cmd.Split(new char[] { ' ' }, 2);
            if (acmd == null || acmd.Length < 1)
                return null;
            string c2 = acmd[0].ToLower();

            foreach (SCheatCommand c in v_Commands)
            {
                if (c.szCommand == c2)
                    return c;
            }

            string p = acmd.Length > 1 ? acmd[1].ToLower() : "";
            Globals.Log.Info("SCheatCommand: {0},{1}", c2, p);
            return null;
        }

        // delegate for the callback
        public delegate void RunDelPMore(Player pPlayer, List<string> vToken);
        public delegate void RunDelP1(Player pPlayer, string vToken);
        public delegate void RunDelPOnly(Player pPlayer);

        public bool CanRun(string szCmd, int nPermission)
        {
            return true;
        }

        public void Run(Player pPlayer, string szCmd)
        {

            if (this.nParameters > 0)
            {
                List<string> vParams = new List<string>();
                string[] sa = szCmd.Split(' ');
                foreach (string s in sa)
                {
                    if(!String.IsNullOrEmpty(s))
                        vParams.Add(s);
                }
                if (this._runPMore != null)
                    this._runPMore(pPlayer, vParams);

//                 int numMinus1 = this.nParameters - 1;
//                 if ( numMinus1 != 0)
//                 {
//                     if (numMinus1 == 1 )
//                     {
//                         *(v3 - 24) = 0;
//                         *(v3 - 20) = 0;
//                         *(v3 - 16) = 0;
//                         v7 = *(v3 + 12);
//                         v8 = *(v7 + 24) < 0x10u;
//                         *(v3 - 4) = 0;
//                         if ( v8 )
//                             v9 = (v7 + 4);
//                         else
//                             v9 = *(v7 + 4);
//                         XStringUtil::Split(v9, (v3 - 28), " ", 0);
//                         v4->_run(*(v3 + 8), (v3 - 28));
//                         std::vector<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_std::allocator<std::basic_string<char_std::char_traits<char>_std::allocator<char>>>>::_Tidy((v3 - 28));
//                     }
//                 }
//                 else
//                 {
//                     (this->_run)(*(v3 + 8));
//                 }
            }
            else
            {
                if (this._runP1 != null)
                    this._runP1(pPlayer, szCmd);
                else if (this._runPOnly != null)
                    this._runPOnly(pPlayer);

            }

//            Globals.Log.Info("SCheatCommand: {0},{1}", this.szCommand, szCmd);
        }
// 
//             switch(cmd)
//             {
//                 case "sitdown":
// //                    onCheatSitdown();
//                     break;
// 
//                 case "gicon":
//                     //                    onCheatSitdown();
//                     break;
// 
//                 case "sitdown":
//                     //                    onCheatSitdown();
//                     break;
// 
//                 case "sitdown":
//                     //                    onCheatSitdown();
//                     break;
//                 case "sitdown":
//                     //                    onCheatSitdown();
//                     break;
//                 case "sitdown":
//                     //                    onCheatSitdown();
//                     break;
//                 case "sitdown":
//                     //                    onCheatSitdown();
//                     break;
//                 case "sitdown":
//                     //                    onCheatSitdown();
//                     break;
//                 case "sitdown":
//                     //                    onCheatSitdown();
//                     break;
//                 case "sitdown":
//                     //                    onCheatSitdown();
//                     break;
//                 case "sitdown":
//                     //                    onCheatSitdown();
//                     break;
//                 case "sitdown":
//                     //                    onCheatSitdown();
//                     break;
//                 case "sitdown":
//                     //                    onCheatSitdown();
//                     break;
// 
//             }
//         }

        public SCheatCommand(string szCmd, RunDelP1 pRun1, bool bPermission, int nParamCount)
        {
            this.szCommand = szCmd;
            this._runP1 = pRun1;
            this._runPMore = null;
            this._runPOnly = null;
            this.bPermissionRequired = bPermission;
            this.nParameters = nParamCount;
        }

        public SCheatCommand(string szCmd, RunDelPOnly _pOnly,bool bPermission, int nParamCount)
        {
            this.szCommand = szCmd;
            this._runP1 = null;
            this._runPMore = null;
            this._runPOnly = _pOnly;
            this.bPermissionRequired = bPermission;
            this.nParameters = nParamCount;
        }

        public SCheatCommand(string szCmd, RunDelPMore _pRunMore, bool bPermission, int nParamCount)
        {
            this.szCommand = szCmd;
            this._runP1 = null;
            this._runPMore = _pRunMore;
            this._runPOnly = null;
            this.bPermissionRequired = bPermission;
            this.nParameters = nParamCount;
        }

        // Typedef        :   , Type: function  *
        // Typedef        :   , Type: function  *
        // Typedef        :   , Type: function  *
        // Typedef        :   , Type: function  *
        public string szCommand;                // 0x0
        public RunDelPMore _runPMore;                        // 0x4
        public RunDelP1 _runP1;
        public RunDelPOnly _runPOnly;
        public bool bPermissionRequired;        // 0x8
        public int nParameters;                 // 0xC
        // Function       :   public bool SCheatCommand::CanRun(int)
        // Function       :   public void SCheatCommand::Run(struct StructPlayer *, const class std::basic_string<char,std::char_traits<char>,std::allocator<char> > &)


        public static void onCheatNotice(Player pPlayer, string strNotice)
        {
            if (!String.IsNullOrEmpty(strNotice))
            {
                Messages.SendGlobalChatMessage(20, pPlayer.GetName(), strNotice,0);
            }
        }

        public static void onCheatScript(Player pClient, string pScript)
        {
            LuaVM.Instance.RunString(pClient,pScript);
//             v1 = *pScript;
//             v2 = 0;
//             v3 = 0;
//             v4 = 0;
//             v5 = pScript;
//             if ( !*pScript )
//                 goto LABEL_21;
//             do
//             {
//                 if ( v1 == 40 )
//                     ++v4;
//                 if ( v1 == 41 )
//                     --v4;
//                 if ( v1 == 39 )
//                     ++v2;
//                 if ( v1 == 34 )
//                     ++v3;
//                 ++v5;
//                 v1 = *v5;
//             }
//             while ( *v5 );
//             if ( !v4 )
//             {
//         LABEL_21:
//                 v7 = v2 & 0x80000001;
//                 v6 = v7 == 0;
//                 if ( v7 < 0 )
//                     v6 = ((v7 - 1) | 0xFFFFFFFE) == -1;
//                 if ( v6 )
//                 {
//                     v9 = v3 & 0x80000001;
//                     v8 = v9 == 0;
//                     if ( v9 < 0 )
//                         v8 = ((v9 - 1) | 0xFFFFFFFE) == -1;
//                     if ( v8 )
//                     {
//                         v10 = LuaVM::Inst();
//                         LuaVM::RunString(v10, pScript, 0);
//                     }
//                 }
//             }
        }


        public static void onRunScript(Player pClient, string strMessage)
        {
//            List<string> vCmdAndParam = new List<string>(); // -116 -74h
            int nPermission;                                // -16  -10h
// .text:0047D675 pClient         = dword ptr  8    8
// .text:0047D675 strMessage      = dword ptr  12   0Ch

            nPermission = pClient.m_nPermission;
            string[] cmds = strMessage.Split(new char[] {' ','(',')','\"','\''});
//            XStringUtil::Split((v6 + 5), (v2 - 116), " (),\"'", 1);
            if (cmds.Length == 1 && GameContent.IsAllowedCommand(nPermission, cmds[0], null)
              || cmds.Length >= 2
              && GameContent.IsAllowedCommand(nPermission, cmds[0], cmds[1]))
            {
                onCheatScript(pClient,strMessage);
//                 if ( std::vector<StructRoamer::ROAMING_CREATURE_INFO_std::allocator<StructRoamer::ROAMING_CREATURE_INFO>>::size((v2 - 116)) <= 1
//                   || ((v15 = std::vector<std::basic_string<char_std::char_traits<char>_std::allocator<char>>_std::allocator<std::basic_string<char_std::char_traits<char>_std::allocator<char>>>>::operator__(
//                                  (v2 - 116),
//                                  1u),
//                        v15->_Myres < 0x10) ? (v16 = &v15->_Bx) : (v16 = *&v15->_Bx._Buf[0]),
//                       strnicmp(v16, "warp", 4u)) )
//                 {
//                     v17 = *(v2 + 8);
//                     v18 = nPermission;
//                     *(v2 - 20) = v18;
//                     LODWORD(v18) = *v17;
//                     *(v2 - 28) = 0;
//                     *(v2 - 24) = 0;
//                     *(v2 - 36) = 0;
//                     *(v2 - 32) = 0;
//                     *(v2 - 44) = 0;
//                     *(v2 - 40) = 0;
//                     *(v2 - 52) = 0;
//                     *(v2 - 48) = 0;
//                     *(v2 - 60) = 0;
//                     *(v2 - 56) = 0;
//                     *(v2 - 68) = 0;
//                     *(v2 - 64) = 0;
//                     *(v2 - 76) = 0;
//                     *(v2 - 72) = 0;
//                     *(v2 - 84) = 0;
//                     *(v2 - 80) = 0;
//                     *(v2 - 16) = HIDWORD(v18);
//                     v19 = (*(v18 + 64))();
//                     v20 = *(v2 + 8);
//                     *(v2 - 92) = v19;
//                     *(v2 - 88) = v19 >> 32;
//                     v21 = StructPlayer::GetAccountID(v20);
//                     v5 = *(v4 + 24) < 0x10u;
//                     *(v2 - 100) = v21;
//                     *(v2 - 96) = v21 >> 32;
//                     if ( v5 )
//                         v22 = v4 + 4;
//                     else
//                         v22 = *v13;
//                     v23 = v22;
//                     v24 = *(v2 + 8);
//                     v25 = v24->baseclass_0.baseclass_0.baseclass_0.baseclass_0.vfptr[3].GetHandle(*(v2 + 8));
//                     v26 = StructPlayer::GetAccountName(v24);
//                     LOG::Log11N4S(
//                         0x899u,
//                         (v2 - 100),
//                         (v2 - 92),
//                         (v2 - 20),
//                         (v2 - 84),
//                         (v2 - 76),
//                         (v2 - 68),
//                         (v2 - 60),
//                         (v2 - 52),
//                         (v2 - 44),
//                         (v2 - 36),
//                         (v2 - 28),
//                         v26,
//                         -1,
//                         v25,
//                         -1,
//                         &unk_5F42BB,
//                         0,
//                         v23,
//                         -1);
//                }
            }
        }

        public static void onCheatPosition(Player pClient)
        {
            ArPosition pos = pClient.GetCurrentPosition(Globals.GetArTime());
            string msg = String.Format("<BR>X: {0}, Y: {1}, Layer: {2}<BR>", (int)pos.x, (int)pos.y, pClient.m_layer);
            Messages.SendChatMessage(false, 30, "@SYSTEM", pClient, msg, 0);
        }

        public static void onBattleMode(Player pPlayer, List<string> vToken)
        {
            RLock rl;
            AutoLock al;

            if (vToken.Count  >= 2)
            {
                uint id = Marshal.ToUInt32(vToken[0]);
                Creature c = Creature.get(id) as Creature;
                if (c == null)
                    return;

                if (c.IsPlayer() && pPlayer.m_hHandle == c.m_hHandle)
                {
                    pPlayer.m_bIsBattleMode = true;
                }
                else
                {
                    if (!c.IsSummon())
                        return;

                    Summon s = pPlayer.GetSummon(c.m_hHandle);
                    if (s != null)
                        s.m_bIsBattleMode = true;
                }

                rl = RappelzServer.Instance._LockObjectWithVisibleRange(c);
                al = new AutoLock(rl.handle);
                Messages.BroadcastStatusMessage(c);
            }
        }

        public static void onCheatSitdown(Player pPlayer)
        {
            RLock rl = RappelzServer.Instance._LockObjectWithVisibleRange(pPlayer);
            AutoLock al = new AutoLock(rl.handle);

            if (!pPlayer.mv.bIsMoving || !pPlayer.bIsInWorld)
            {
                if (pPlayer.IsActable())
                {
                    if (pPlayer.IsSitdownable())
                    {
                        if ((pPlayer.m_StatusFlag & Creature.StatusFlags.FormChanged) != 0)
                        {
                            Messages.SendChatMessage(false, 20, "@NOTICE", pPlayer, "@440", 0);
                        }
                        else
                        {
                            if (pPlayer.m_hEnemy != 0)
                                pPlayer.CancelAttack();
                            pPlayer.m_bIsSitDown = true;
                            Messages.BroadcastStatusMessage(pPlayer);
                        }
                    }
                }
            }
//            ArcadiaAutoLock::_ArcadiaAutoLock((v2 - 32));

        }

        public static void onCheatStandUp(Player pPlayer)
        {
            RLock rl = RappelzServer.Instance._LockObjectWithVisibleRange(pPlayer);
            AutoLock al = new AutoLock(rl.handle);

            if (pPlayer.m_BoothStatus == Player.BoothStatus.IsNotBooth)
            {
                pPlayer.m_bIsSitDown = false;
                Messages.BroadcastStatusMessage(pPlayer);
            }
//            ArcadiaAutoLock::_ArcadiaAutoLock((v2 - 32));
        }


        public static void onGuildCreate(Player pPlayer, List<string> vToken)
        {
            if (pPlayer.GetLastContactLong("guild") != 0 && vToken.Count >= 1)
            {
                string name = vToken[0];
                if (!String.IsNullOrEmpty(name) && name.Length <= 30)
                {
                    string cmd = "on_create_guild( '" + name + "' )";
                    LuaVM.Instance.RunString(pPlayer, cmd);
                    pPlayer.SetLastContact("guild", 0);
                    pPlayer.Save(true);
                }
            }

        }

        public static void onRequestGuildIconInfo(Player pPlayer, List<string> vToken)
        {
            int nGuildIconSize;         // -80  -50h
            int nGuildId;               // -76  -4Ch
            string strGuildName;        // -72  -48h
            string strGuildIcon="";        // -44  -2Ch

            nGuildId = Marshal.ToInt32(vToken[0]);
            if (nGuildId != 0)
            {
                nGuildIconSize = GuildManager.Instance.GetGuildIconSize(nGuildId);
                if (nGuildIconSize != 0)
                {
                    strGuildIcon = GameRule.guild_icon_base_url;
                    strGuildIcon += GuildManager.Instance.GetGuildIcon(nGuildId);
                }
                strGuildName = GuildManager.Instance.GetGuildName(nGuildId);
                Messages.PrintfChatMessage(true,110,"@GUILD",pPlayer,"GICON|{0}|{1}|{2}|{3}",nGuildId,strGuildName,strGuildIcon,nGuildIconSize);
            }
        }

        public static void onGuildIconUpdate(Player pClient)
        {
            PacketOut pak = new PacketOut(652);
            pak.WriteUInt32(390797);
            pak.WriteUInt32(30687524);
            pak.WriteUInt32(5643820);
            pak.FillString("Game001", 32);
            pClient.Connection.SendTCP(pak);
        }

        public static void onGuildRaidSeigeTip(Player pClient)
        {
            string buff = String.Format("GRAIDSIEGETIP|0|0| | |0|0|");
            Messages.SendChatMessage(false, 110, "@GUILD", pClient.m_hHandle, buff, 0);

        }

        
    }


}
